/*
 * @FilePath: /gis-platform/src/views/shaoxing-map/config/config.js
 * @Author: 张文鑫
 * @Date: 2024-12-02 17:33:41
 * @Description: 地图配置及操作逻辑
 */
// 导入模块
import { Vector as VectorSource } from "ol/source";
import { Vector as VectorLayer } from "ol/layer";
import { Style, Text, Fill, Stroke } from "ol/style";
import axios from "axios";
import { convertTestJson } from "@/utils/index";
import GeoJSON from "ol/format/GeoJSON";
import TileLayer from "ol/layer/Tile";
import WMTS from "ol/source/WMTS";
import WMTSTileGrid from "ol/tilegrid/WMTS";
import { get as getProjection } from "ol/proj";
import { getTopLeft, getWidth } from "ol/extent";
import CryptoJS from "crypto-js";

// =============== JWT 认证相关 ===============
/**
 * Base64 URL 编码函数
 * @param {*} str 待编码的字符串
 * @returns {string} 编码后的字符串
 */
function base64UrlEncode(str) {
  const encodedSource = CryptoJS.enc.Base64.stringify(str);
  return encodedSource.replace(/=+$/, "").replace(/\+/g, "-").replace(/\//g, "_");
}

/**
 * 生成JWT令牌
 * @param {string} accessKey - 访问密钥
 * @param {string} secretKey - 秘密密钥
 * @returns {string} JWT令牌
 */
function generateJWT(accessKey, secretKey) {
  const header = JSON.stringify({ alg: "HS256", typ: "JWT" });
  const payload = JSON.stringify({
    key: accessKey,
    exp: new Date().setHours(new Date().getHours() + 1),
  });

  const beforeSign =
    base64UrlEncode(CryptoJS.enc.Utf8.parse(header)) + "." + base64UrlEncode(CryptoJS.enc.Utf8.parse(payload));
  const signature = CryptoJS.HmacSHA256(beforeSign, secretKey);
  return beforeSign + "." + base64UrlEncode(signature);
}

// 密钥配置 (后端实现时应移除)
const CONFIG = {
  accessKey: "BCDSGA_9ecfbd973839a52fcb943b28f661cd0f",
  secretKey: "BCDSGS_26eb426798a2919a421dde6f482f7100",
  mapUrls: {
    vector: "https://ibcdsg.zj.gov.cn:8443/restapi/prod/IC33000020220315000001/services/wmts/emap/default/oss",
    image: "https://ibcdsg.zj.gov.cn:8443/restapi/prod/IC33000020220406000002/services/wmts/imgmap/default/oss",
  },
  apiUrls: {
    county: "http://118.89.134.12:8025/sxmap/data/county.json",
    town: "http://118.89.134.12:8025/sxmap/data/town.json",
    village: "http://118.89.134.12:8025/service/getBQueryResult",
  },
};

// 用于缓存地理数据
const geoDataCache = new Map();

// 统一地图颜色
const MAP_COLOR = "#061c65";

// 设置图例颜色的函数 - 简化版本
export async function setLegendColors(colors, map, organId = "3306", icon = 0) {
  // 这个函数保留为了兼容性，但不再处理颜色逻辑
  if (!map) return;

  try {
    // 获取所有矢量图层并触发重新渲染
    const allLayers = map.getLayers().getArray();
    const vectorLayers = allLayers.filter(
      (layer) => layer instanceof VectorLayer && layer.getSource && layer.getSource() instanceof VectorSource
    );

    for (const layer of vectorLayers) {
      layer.changed();
    }

    console.log("图层更新完成");
  } catch (error) {
    console.error("更新图层出错:", error);
  }
}

// 生成JWT令牌
const jwtToken = generateJWT(CONFIG.accessKey, CONFIG.secretKey);

/**
 * 获取认证URL
 * @param {string} baseUrl - 基础URL
 * @returns {string} 添加认证信息的URL
 */
const getAuthUrl = (baseUrl) => {
  return baseUrl + "?jwt=" + jwtToken + "&x-bg-auth-type=jwt_auth";
};

// =============== 地图投影和瓦片网格配置 ===============
const projection = getProjection("EPSG:4326");
const projectionExtent = projection.getExtent();
const tileSize = getWidth(projectionExtent) / 256;

// 生成分辨率和矩阵ID数组
const generateResolutionsAndMatrixIds = (levels = 20) => {
  const resolutions = new Array(levels);
  const matrixIds = new Array(levels);

  for (let z = 0; z < levels; ++z) {
    resolutions[z] = tileSize / Math.pow(2, z);
    matrixIds[z] = z;
  }

  return { resolutions, matrixIds };
};

const { resolutions, matrixIds } = generateResolutionsAndMatrixIds();

// =============== 图层创建 ===============
/**
 * 创建WMTS图层
 * @param {string} url - 服务URL
 * @param {string} layer - 图层名称
 * @returns {TileLayer} WMTS图层
 */
function createWMTSLayer(url, layer = "emap") {
  return new TileLayer({
    opacity: 1,
    source: new WMTS({
      url: getAuthUrl(url),
      layer: layer,
      matrixSet: "EPSG:4326",
      format: "image/png",
      projection: projection,
      tileGrid: new WMTSTileGrid({
        origin: getTopLeft(projectionExtent),
        resolutions: resolutions,
        matrixIds: matrixIds,
      }),
      style: "default",
      wrapX: true,
    }),
  });
}

// 全局数据存储
let townData = { type: "FeatureCollection", features: [] };
let hoveredFeature = null;

// 创建基础图层
export const vec_wLayer = createWMTSLayer(CONFIG.mapUrls.vector);
export const img_wLayer = createWMTSLayer(CONFIG.mapUrls.image);

// 创建一个空的矢量图层
const vectorSource = new VectorSource();
export const vectorLayer = new VectorLayer({
  source: vectorSource,
  zIndex: 3, // 确保在所有图层最上层
});

// =============== 样式工具函数 ===============
/**
 * 创建文本样式
 * @param {string} text - 显示文本
 * @param {object} options - 文本样式选项
 * @returns {Text} 文本样式对象
 */
function createTextStyle(
  text,
  { isBold = false, fontSize = 12, color = "#ffffff", strokeColor = "#003366", offsetY = -10 } = {}
) {
  return new Text({
    text: text,
    font: `${isBold ? "bold " : ""}${fontSize}px sans-serif`,
    fill: new Fill({ color }),
    stroke: new Stroke({
      color: strokeColor,
      width: 3,
    }),
    offsetY,
  });
}

// =============== 图层创建函数 ===============
/**
 * 创建区域图层
 * @param {string} organId - 组织机构ID
 * @returns {Promise<VectorLayer>} 矢量图层
 */
export async function createDistrictLayer(organId = "3306") {
  try {
    const organIdLength = organId.length;
    let geoJsonData = { type: "FeatureCollection", features: [] };
    let levelType = "county"; // 默认为县级

    // 检查缓存中是否有此区域的数据
    const cacheKey = `geo_${organId}`;
    if (geoDataCache.has(cacheKey)) {
      console.log(`使用缓存的地理数据: ${cacheKey}`);
      geoJsonData = geoDataCache.get(cacheKey);

      // 创建矢量图层并返回，不再重复获取数据
      return createVectorLayerFromGeoData(geoJsonData, organId);
    }

    // 根据organId长度确定区域级别和数据获取方式
    if (organIdLength === 6) {
      // 镇/街道级别
      levelType = "town";

      // 获取镇级数据
      if (townData.features.length === 0) {
        try {
          // 使用fetch替代axios，解决CORS问题
          const response = await fetch(CONFIG.apiUrls.town, {
            method: "GET",
            mode: "cors",
            headers: {
              Accept: "application/json",
              "Content-Type": "text/plain", // 使用简单内容类型避免预检请求
            },
          });

          if (!response.ok) {
            throw new Error(`HTTP error! Status: ${response.status}`);
          }

          const data = await response.json();
          townData = convertTestJson(data);
        } catch (error) {
          console.error("获取镇级数据失败:", error);
          //如果fetch失败，回退到axios
          const response = await axios.get(CONFIG.apiUrls.town, {
            headers: {
              "Content-Type": "text/plain",
            },
          });
          townData = convertTestJson(response.data);
        }

        // 设置特性级别和bh
        townData.features.forEach((feature) => {
          feature.properties.level = "town";

          // 确保每个特征都有bh属性
          if (!feature.properties.bh && feature.properties.id) {
            feature.properties.bh = feature.properties.id;
          }
        });
      }

      // 筛选指定父级编码的镇
      geoJsonData.features = townData.features.filter((feature) => {
        return feature.properties.pcode == organId;
      });

      // 缓存处理后的数据
      geoDataCache.set(cacheKey, geoJsonData);
    } else if (organIdLength === 9) {
      // 村/社区级别
      levelType = "village";

      // 获取村级数据
      const response = await axios.get(CONFIG.apiUrls.village, {
        params: {
          appid: "SXZZB",
          name: "queryVillageNArea",
          pcode: organId,
        },
      });

      if (!response.data?.data) {
        console.warn("未获取到村级数据");
        return null;
      }

      geoJsonData = convertTestJson(response.data);

      // 设置特性级别和bh
      geoJsonData.features.forEach((feature) => {
        feature.properties.level = "village";

        // 确保每个特征都有bh属性
        if (!feature.properties.bh && feature.properties.id) {
          feature.properties.bh = feature.properties.id;
        }
      });

      // 缓存处理后的数据
      geoDataCache.set(cacheKey, geoJsonData);
    } else {
      // 县/区级别或其他情况
      // 获取所有区县数据
      try {
        // 使用fetch替代axios，解决CORS问题
        const url = `${CONFIG.apiUrls.county}?v=2024102301`;
        const response = await fetch(url, {
          method: "GET",
          mode: "cors",
          headers: {
            Accept: "application/json",
            "Content-Type": "text/plain", // 使用简单内容类型避免预检请求
          },
        });

        if (!response.ok) {
          throw new Error(`HTTP error! Status: ${response.status}`);
        }

        const data = await response.json();
        geoJsonData = convertTestJson(data);
      } catch (error) {
        console.error("获取县级数据失败:", error);
        //如果fetch失败，回退到axios
        const response = await axios.get(CONFIG.apiUrls.county, {
          params: { v: "2024102301" },
        });
        geoJsonData = convertTestJson(response.data);
      }

      // 设置特性级别和bh
      geoJsonData.features.forEach((feature) => {
        feature.properties.level = "county";

        // 确保每个特征都有bh属性
        if (!feature.properties.bh && feature.properties.id) {
          feature.properties.bh = feature.properties.id;
        }
      });

      // 缓存处理后的数据
      geoDataCache.set(cacheKey, geoJsonData);
    }

    // 创建矢量图层
    const layer = createVectorLayerFromGeoData(geoJsonData, organId);

    return layer;
  } catch (error) {
    console.error("获取区域数据失败:", error);
    return null;
  }
}

/**
 * 创建矢量图层 - 从GeoJSON数据
 */
function createVectorLayerFromGeoData(geoJsonData, organId) {
  const levelType = geoJsonData.features[0]?.properties?.level || "county";

  // 创建GeoJSON格式转换器并读取特征
  const geoJsonFormat = new GeoJSON();
  const features = geoJsonFormat.readFeatures(geoJsonData);

  // 确保OpenLayers特征对象包含bh属性
  features.forEach((feature) => {
    const props = feature.getProperties();
    // 如果没有bh属性但有id属性，使用id作为bh
    if (!props.bh && props.id) {
      feature.set("bh", props.id);
    }
    // 如果level属性在properties中但不在feature顶层，移动它
    if (props.properties && props.properties.level && !props.level) {
      feature.set("level", props.properties.level);
    }
  });

  return new VectorLayer({
    source: new VectorSource({
      features: features,
    }),
    style: function (feature) {
      const isHovered = feature === hoveredFeature;
      return updateStyleForHoveredFeature(feature, isHovered);
    },
    zIndex: levelType === "county" ? 2 : levelType === "town" ? 2.5 : 3,
    properties: {
      level: levelType,
      bh: organId,
    },
  });
}

// =============== 事件处理和交互逻辑 ===============
/**
 * 添加地图交互和缩放监听
 * @param {Map} map - OpenLayers地图实例
 * @returns {Function} 清理函数
 */
export function addZoomListener(map) {
  // ===== 悬停效果处理 =====
  map.on("pointermove", (evt) => {
    const pixel = map.getEventPixel(evt.originalEvent);

    // 更改鼠标样式
    const hit = map.hasFeatureAtPixel(pixel);
    map.getTargetElement().style.cursor = hit ? "pointer" : "";

    // 获取鼠标下的特性
    const feature = map.forEachFeatureAtPixel(pixel, (feature) => feature);

    // 处理悬停效果
    if (feature !== hoveredFeature) {
      // 保存旧的悬停特性
      const oldHovered = hoveredFeature;

      // 更新当前悬停特性
      hoveredFeature = feature;

      // 重绘所有矢量图层，因为我们现在使用统一样式处理
      map
        .getLayers()
        .getArray()
        .filter((layer) => layer instanceof VectorLayer)
        .forEach((layer) => layer.changed());
    }
  });

  // ===== 视图变化处理 =====
  map.on("moveend", () => {
    const zoom = map.getView().getZoom();

    // 在缩放级别很小时处理
    if (zoom < 9) {
      console.log("缩放级别较小:", zoom);
    }
  });

  // ===== 点击事件处理 - 这部分将被IrsMap.vue中的逻辑替代 =====
  // 现在地图点击仅用于调试输出
  map.on("click", (evt) => {
    const feature = map.forEachFeatureAtPixel(evt.pixel, (feature) => feature);
    if (!feature) return;

    // 输出点击的特征属性用于调试
    console.log("地图点击特征:", {
      level: feature.getProperties().level,
      name: feature.getProperties().name,
      bh: feature.getProperties().bh,
      zoom: map.getView().getZoom(),
    });
  });

  // 在组件销毁时清理
  return () => {
    hoveredFeature = null;
  };
}

// 统一样式处理函数
export function updateStyleForHoveredFeature(feature, isHovered) {
  if (!feature) return null;

  // 安全地获取属性，避免undefined错误
  const getName = () => {
    try {
      return feature.get("name") || "";
    } catch (e) {
      console.warn("获取feature名称失败", e);
      return "";
    }
  };

  const name = getName();

  // 统一使用固定颜色
  const fillColor = MAP_COLOR;
  const strokeColor = "#0066cc";
  const strokeWidth = isHovered ? 3 : 2;
  const fontSize = isHovered ? 14 : 12;
  const textOffsetY = -15;

  return new Style({
    fill: new Fill({ color: fillColor }),
    stroke: new Stroke({
      color: strokeColor,
      width: strokeWidth,
    }),
    text: createTextStyle(name, {
      isBold: isHovered,
      fontSize,
      strokeColor: "#003366",
      offsetY: textOffsetY,
    }),
  });
}
